# encoding: utf-8
import datetime
import logging

from django.core.cache import cache
from rest_framework import serializers

from main import config
from main.common.redis.redis_keys import PHONE_CODE_KEY
from main.common.utils.utils import get_client_ip, qq_captcha_validate
from main.common.valid.validators import validate_mobilephone

logger = logging.getLogger(__name__)


class QQCaptchaField(serializers.CharField):
    """
    QQ验证码
    doc: https://007.qq.com/product.html
    """

    def to_internal_value(self, data):

        data = super(QQCaptchaField, self).to_internal_value(data)
        if config.ENV in ["test_ci"]:
            return data

        if len(data.split(";")) != 2:
            raise serializers.ValidationError("验证码校验失败")
        ticket, randstr = data.split(";")
        request = self.context["request"]
        uip = get_client_ip(request)
        if qq_captcha_validate(ticket=ticket, randstr=randstr, uip=uip):
            return "success"
        raise serializers.ValidationError("验证码校验失败")


class PhoneCodeAuthMixin(serializers.Serializer):

    phone = serializers.CharField(
        required=True,
        help_text="手机号码",
        write_only=True,
    )
    code = serializers.CharField(
        help_text="短信验证码",
        required=True,
        write_only=True,
    )

    def validate_cellphone(self, value):
        value = value.strip()
        validate_mobilephone(value)
        return value

    def phone_code_validate(self, code, cellphone):
        cellphone = cellphone.strip()
        res = cache.get(PHONE_CODE_KEY % cellphone)
        if not res or res != code:
            try:
                raise AssertionError(
                    "短信验证码错误！ {} phone:{} `{}` != `{}`".format(
                        config.ENV, cellphone, res, code
                    )
                )
            except AssertionError:
                logger.exception("短信验证码错误!")
            raise serializers.ValidationError("短信验证码错误！")
        cache.delete(PHONE_CODE_KEY % cellphone)
        return True

    def validate(self, attrs):
        self.phone_code_validate(attrs["code"], attrs["phone"])
        attrs.pop("code", "")
        return attrs

    class Meta:
        abstract = True
